package com.lw.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.lw.common.enums.GlobalTypeEnum;
import com.lw.common.utils.GlobalConstants;
import com.lw.common.utils.StrUtils;
import com.lw.common.vo.Option;
import com.lw.entity.TbUserRole;
import com.lw.service.TbRoleMenuService;
import com.lw.service.TbUserRoleService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.lw.entity.TbRole;
import com.lw.mapper.TbRoleMapper;
import com.lw.service.TbRoleService;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;

import static com.lw.entity.table.TbRoleTableDef.TB_ROLE;
import static com.lw.entity.table.TbUserRoleTableDef.TB_USER_ROLE;

/**
 * 角色管理 服务层实现。
 *
 * @author lw
 * @since 2024年12月08日 07:53:39
 */
@Service
public class TbRoleServiceImpl extends ServiceImpl<TbRoleMapper, TbRole> implements TbRoleService {
    private static final Logger logger = LoggerFactory.getLogger(TbRoleMenuServiceImpl.class);
    @Resource
    private TbRoleMenuService tbRoleMenuService;
    @Resource
    private TbUserRoleService tbUserRoleService;

    /**
     * 获取用户角色 并且缓存
     */
    @Cacheable(cacheNames = "roleCache",key = "#loginId")
    @Override
    public List<String> getRoleIds(String loginId) {
        return queryChain().select(TB_ROLE.CODE).from(TB_ROLE)
                .leftJoin(TB_USER_ROLE).on(TB_ROLE.ID.eq(TB_USER_ROLE.ROLE_ID))
                .and(TB_USER_ROLE.USER_ID.eq(loginId)).listAs(String.class);

    }

    /**
     * 是否是超级管理员
     *
     * @param id 用户id
     * @return true 超级管理员 false 普通管理员
     */
    @Override
    public boolean isRoot(Long id) {
        List<String> roleList = queryChain().select(TB_ROLE.CODE).from(TB_ROLE)
                .leftJoin(TB_USER_ROLE).on(TB_ROLE.ID.eq(TB_USER_ROLE.ROLE_ID))
                .and(TB_USER_ROLE.USER_ID.eq(id)).listAs(String.class);
        // 超级管理员
        return roleList.contains(GlobalConstants.ROOT_ROLE_NAME);
    }

    @Override
    public Page<TbRole> getRolePage(TbRole role) {
        long pageNumber = role.getPageNum();
        long pageSize = role.getPageSize();
        Page<TbRole> page = new Page<>(pageNumber, pageSize);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.like(TB_ROLE.NAME.getName(), role.getKeywords(), StrUtils.hasLength(role.getKeywords()));
        queryWrapper.ne(TB_ROLE.CODE.getName(), GlobalConstants.ROOT_ROLE_NAME);
        queryWrapper.eq(TB_ROLE.IS_DELETED.getName(), GlobalTypeEnum.STATE_NO_DELETE.getValue());
        queryWrapper.orderBy(TB_ROLE.SORT.getName());
        return page(page, queryWrapper);
    }

    @Transactional
    @Override
    public Boolean removeRoleById(Long id) {
        List<TbUserRole> userListByRoleId = tbUserRoleService.getUserListByRoleId(id);
        if (!userListByRoleId.isEmpty()) {
            throw new RuntimeException("该角色下有用户，不允许删除");
        }
        boolean b = removeById(id);
        logger.info("删除角色成功：{}", id);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(TB_USER_ROLE.ROLE_ID.getName(), id);
        return b && tbRoleMenuService.remove(queryWrapper);
    }

    @Override
    public List<Option<Long>> getRoleListOptions() {
        // 查询数据
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select(TB_ROLE.ID, TB_ROLE.NAME);
        queryWrapper.ne(TB_ROLE.CODE.getName(), GlobalConstants.ROOT_ROLE_NAME, !StpUtil.getRoleList().contains(GlobalConstants.ROOT_ROLE_NAME));
        queryWrapper.orderBy(TB_ROLE.SORT.getName());
        List<TbRole> roleList = list(queryWrapper);
        return roleList.stream().map(r -> {
            Option<Long> option = new Option<>();
            option.setValue(r.getId());
            option.setLabel(r.getName());
            return option;
        }).collect(Collectors.toList());
    }
}
